package dominio;

import java.util.ArrayList;
import java.util.Collections;
import com.lanchita.excepciones.EstadoErroneoException;

public class Buscador {

	private ArrayList<Gestionador> aerolineas;
	
	public Buscador() {
		super();
		this.aerolineas = new ArrayList<Gestionador>();
	}

	public void agregarAerolinea(Gestionador gestionadorDeUnaAerolinea) {
		this.aerolineas.add(gestionadorDeUnaAerolinea);
	}

	public ArrayList<Viaje> buscarAsientosQueSeAjustenA(Busqueda busqueda , Usuario usuario) {
		// TODO verificar que tenga los campos obligatorios != null. Si no,
		// excepcion.

		if (busqueda.getFecha() == null ||
			busqueda.getCiudadOrigen() == null ||
			busqueda.getCiudadDestino() == null)
			
			throw new BusinessException("Fecha, Origen y/o Destino no ingresados!");

		ArrayList<Viaje> viajes = new ArrayList<Viaje>();

		for (int i = 0; i < aerolineas.size(); i++) 
		{
			ArrayList<Asiento> asientosOrigenAEscala1 = aerolineas.get(i).buscarAsientosQueTengan(busqueda.getCiudadOrigen(), 
																								  null,
																								  busqueda.getFecha());
			for (Asiento asiento : asientosOrigenAEscala1) 
			{
				//if (asiento.getDestino() != busqueda.getCiudadDestino())
				if (asiento.getDestino().compareTo(busqueda.getCiudadDestino()) != 0)
				{
					if(busqueda.esConEscala())
					{
						ArrayList<Asiento> asientosEscala1Escala2 = aerolineas.get(i).buscarAsientosSinFecha(asiento.getDestino(), null);

						for (Asiento asientoEscala1Escala2 : asientosEscala1Escala2) 
						{
							ArrayList<String> ciudadesAnteriores = new ArrayList<String>();
							ciudadesAnteriores.add(busqueda.getCiudadOrigen());

							if (!ciudadesAnteriores.contains(asientoEscala1Escala2.getDestino()) && asientoEscala1Escala2.saleDespuesQue(asiento)) 
							{
								ArrayList<Asiento> asientosEscala2Destino = aerolineas.get(i).buscarAsientosSinFecha(asientoEscala1Escala2.getDestino(),
																												     busqueda.getCiudadDestino());
								for (Asiento asientoEscala2Destino : asientosEscala2Destino) 
								{
									if (asientoEscala2Destino.saleDespuesQue(asientoEscala1Escala2)) 
									{
										Viaje viaje = new Viaje();
										viaje.agregarAsiento(asiento);
										viaje.agregarAsiento(asientoEscala1Escala2);
										viaje.agregarAsiento(asientoEscala2Destino);
										viaje.setTiempoDeVueloEnMinutos(asiento, asientoEscala2Destino);
										viajes.add(viaje);
										
										for(Asiento unAsientoDeLaEscala : viaje.getEscalas())
											unAsientoDeLaEscala.setAerolinea(aerolineas.get(i).getAerolinea());
									}
								}
														
								if (asientoEscala1Escala2.getDestino() == busqueda.getCiudadDestino()) 
								{
									Viaje viaje = new Viaje();
									viaje.agregarAsiento(asiento);
									viaje.agregarAsiento(asientoEscala1Escala2);
									viaje.setTiempoDeVueloEnMinutos(asiento, asientoEscala1Escala2);
									viajes.add(viaje);
									for(Asiento unAsientoDeLaEscala:viaje.getEscalas())
										unAsientoDeLaEscala.setAerolinea(aerolineas.get(i).getAerolinea());
								}
							}
						}
					}
				}
				else
				{
					Viaje viaje = new Viaje();
					viaje.getEscalas().add(asiento);
					viaje.setTiempoDeVueloEnMinutos(asiento, asiento);
					viajes.add(viaje);
					for(Asiento unAsientoDeLaEscala : viaje.getEscalas())
						unAsientoDeLaEscala.setAerolinea(aerolineas.get(i).getAerolinea());
				}
				
			}
		}
		
		viajes = this.aplicarFiltros(viajes, busqueda, usuario);
		usuario.agregarBusqueda(busqueda);

		return viajes;
	}
	
	public ArrayList<Viaje> ordenarBusqueda(String atributo, int orden, ArrayList<Viaje> viajes){
		if (atributo.equals("precio")) {
			/*Ordenamiento por Precio*/	
			if (orden == 1) {
				/*Ascendente*/
				Collections.sort(viajes, new CompararPrecio());
			} else {
				/*Descendente*/	
				Collections.sort(viajes, Collections.reverseOrder(new CompararPrecio()));
				}
			}
		
		else if (atributo.equals("tiempoDeVuelo")) {
		if (orden == 1) {
			/*orden ascendente*/
			Collections.sort(viajes, new CompararTiempo());
		} else {
			/*orden descendente*/
			Collections.sort(viajes, Collections.reverseOrder(new CompararTiempo()));
		}
		
	}
		return viajes;
		}
	
	
	public ArrayList<Viaje> ordenarBusquedaPorPopularidad(String atributo, int orden, ArrayList<Viaje> viajes){
		if (atributo.equals("popularidad")) {
			/*Ordenamiento por Precio*/	
			if (orden == 1) {
				/*Ascendente*/
				Collections.sort(viajes, new CompararPopularidad());
			} else {
				/*Descendente*/	
				Collections.sort(viajes, Collections.reverseOrder(new CompararPopularidad()));
				}
			}
			
		return viajes;
		}
	
	
	
	
	
	private ArrayList<Viaje> aplicarFiltros(ArrayList<Viaje> viajes, Busqueda busqueda, Usuario usuario) 
	{
		ArrayList<Viaje> viajesADevolver = new ArrayList<Viaje>();
		for( Viaje viaje : viajes )
		{
			ArrayList<Asiento> asientosAntesDeFiltrar = viaje.getEscalas();
			ArrayList<Asiento> asientosDespuesDeFiltrar = busqueda.getFiltro().filtrar(asientosAntesDeFiltrar, busqueda);
			asientosDespuesDeFiltrar = this.filtrarPorUsuario(usuario, asientosDespuesDeFiltrar);
			if(asientosAntesDeFiltrar.size() == asientosDespuesDeFiltrar.size() )
				viajesADevolver.add(viaje);
		}
		return viajesADevolver;
	}

	public ArrayList<Asiento> filtrarPorUsuario(Usuario usuario , ArrayList<Asiento> asientos) 
	{
		ArrayList<Asiento> asientosADevolver = new ArrayList<Asiento>();
		if (!usuario.sosVip())
		/*
		 * Si no es vip eliminar todos los asientos que sea super ofertas TODO
		 * implementar esto como un metodo de la futura clase Asiento
		 */
		{
			for (Asiento asiento : asientos) {
				if (!(asiento.getClase() == "P" && Double.parseDouble(asiento.getPrecio()) < 8000) &&
					!(asiento.getClase() == "E" && Double.parseDouble(asiento.getPrecio()) < 4000))
					asientosADevolver.add(asiento); // Si no es una superoferta
													// la agrego
			}
		}
		else
			asientosADevolver = asientos;
		return asientosADevolver;
	}

	public void comprarAsiento(Asiento asiento, Usuario usuario) {
		// Suponemos que en este paso, siempre vamos a pasar bien los datos del
		// asiento.


//		ArrayList<Asiento> asientos = new ArrayList<Asiento>();
		boolean loEncontro = false;
		int i;
		for (i = 0; i < aerolineas.size() && !loEncontro; i++) {

			if (aerolineas.get(i).getAerolinea()
					.compareTo(asiento.getAerolinea()) == 0)
				loEncontro = true;

			// asientos = aerolineas.get(i).buscarAsientosQueTengan(null,
			// null, asiento.getFechaDeLlegada());
			// if (loEncontro = this.contieneAsiento(asientos, asiento)) {
			// aerolineas.get(i).comprarAsiento(asiento, usuario.getDNI());
			// double montoAPagar = Double
			// .parseDouble(asiento.getPrecio());
			// montoAPagar = montoAPagar
			// + aerolineas.get(i).impuestos(asiento);
			// usuario.paga(montoAPagar);
			// // TODO verificar que no esté reservado, o bien, que
			// // esté
			// // reservado por ESTE usuario! Si no, excepción
			// }
		}
		i--;
		if (loEncontro) {
			try {
			aerolineas.get(i).comprarAsiento(asiento, usuario.getDNI());
			double montoAPagar = Double.parseDouble(asiento.getPrecio());
			montoAPagar = montoAPagar
					+ aerolineas.get(i).impuestos(asiento);
			usuario.paga(montoAPagar);
			} catch (EstadoErroneoException e) {
				throw new BusinessException(
						"Alguien le ganó en la compra/reserva del asiento");
			}
		} else
			throw new RuntimeException(
					"Error asignando la aerol´inea!!");


}

public ArrayList<Gestionador> getAerolineas() {
	return aerolineas;
}

public void setAerolineas(ArrayList<Gestionador> aerolineas) {
	this.aerolineas = aerolineas;
}	
	
//private boolean contieneAsiento(ArrayList<Asiento> asientos, Asiento asiento) {
//	boolean loContiene = false;
//
//	int i;
//	for (i = 0; i < asientos.size(); i++)
//		if (asientos.get(i).getCodigoDeVuelo()
//				.compareTo(asiento.getCodigoDeVuelo()) == 0)
//			if (asientos.get(i).getCodigoDeAsiento()
//					.compareTo(asiento.getCodigoDeAsiento()) == 0
//					&& !loContiene)
//				loContiene = true;
//	return loContiene;
//}

}